killall为什么有时候会找不到进程? | 您所在的位置:网站首页 › roslaunch 未找到命令 › killall为什么有时候会找不到进程? |
前言 在Linux下有很多命令用于杀死进程,它们可以用于不同的场景,例如通过进程名杀死进程,通过pid杀死进程。这些方法我不准备一一列举,本文想说明的一个问题是,为什么明明通过ps找到了进程,但是通过killall却说找不到呢?如果你没有遇到过这样的问题?那你更要注意了! killall简介与kill不同的是,killall可以根据进程名来杀死进程,不像kill,可能先需要使用ps(可以参考《ps命令实例详解》)找到进程id,然后发送信号,就像下面这样: $ ps -ef|grep hello root 15530 6335 0 14:55 pts/4 00:00:00 ./hello $ kill -9 15530这样进程就被我们杀死了,我们可以直接使用killall: $ killall hello是不是觉得方便多了? 而且由于killall是根据名称杀死进程,因此如果当前运行着大量的hello程序,那么可以一次性杀死所有hello程序。 除此之外,它还有很多参数,例如忽略大小写,根据模式匹配进程名,杀死某个时间的进程等等,这里就不详解介绍了,有兴趣的可以查看man killall手册。 今天这里想要说明的是一种killall失效的情况。 killall失效了?我写了一个自己的hello程序,然后尝试使用killall杀死正在运行的hello程序。 $ killall hello hello: no process found什么?竟然说找不到?一个ps丢过来: $ ps -ef|grep hello root 15765 6335 0 15:05 pts/4 00:00:00 ./hello所以killall你到底行不行? 为何为了找出killall失效的原因,我们必须知道它到底是如何通过进程名找到进程的。 这个时候就需要祭出我们的神器strace了,看看killall杀死一个普通进程到底做了哪些事情: $ strace killall hello open("/proc/100/cmdline", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 read(3, "", 1024) = 0 close(3) = 0 open("/proc/104/stat", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 read(3, "104 (ipv6_addrconf) I 2 0 0 0 -1"..., 1024) = 161 close(3) = 0 open("/proc/113/stat", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 read(3, "113 (kstrp) I 2 0 0 0 -1 6923888"..., 1024) = 153 close(3) = 0 open("/proc/137/stat", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 read(3, "137 (charger_manager) I 2 0 0 0 "..., 1024) = 163 close(3) = 0 open("/proc/137/cmdline", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 read(3, "", 1024) = 0打印结果很多,我只提取了部分,可以看到的是,killall会去proc文件系统(proc文件系统可以参考《Linux中不可错过的信息宝库》)下查找各个进程id下的stat文件和cmdline,stat文件是怎样的呢?我们随便找一个看看: $ cat /proc/16131/stat 16131 (hello) S 6335 16131 6335 34820 16131 1077936128 70 0 0 0 0 0 0 0 20 0 1 0 2465163 4321280 194 18446744073709551615 4194304 4196092 140734969955328 0 0 0 0 0 0 1 0 0 17 0 0 0 0 0 0 6295056 6295608 19099648 140734969962804 140734969962812 140734969962812 140734969966576 0我们不要被这么多内容吓到了,可以明显看到的是,里面有hello啊。至此我们可以猜测,killall命令会去读取进程在proc文件系统中的stat文件里的名字。那么如果这么名字和你要杀死的进程对不上不就找不到了吗? 至此,想必你已经明白前面问题的原因了。 如何给自挖坑那么怎样修改stat中显示的名字呢?我们可以使用prcl函数,话不多少,直接看示例代码: //来源:公众号【编程珠玑】 //作者:守望先生 #include #include #include int main(void) { prctl(PR_SET_NAME,"bianchengzhuji"); sleep(100);//防止进程立即退出,便于观察 return 0; }这个时候再编译运行程序查看stat和status中的名字: $ gcc -o hello hello.c $ cat /proc/pid/stat #这里的pid换成示例的进程id 16441 (bianchengzhuji) S 6335 16441 6335 34820 16441 1077936128 69 0 0 0 0 0 0 0 20 0 1 0 2535513 4321280 156 18446744073709551615 4194304 4196188 140724949606512 0 0 0 0 0 0 1 0 0 17 3 0 0 0 0 0 6295056 6295616 31719424 140724949614900 140724949614908 140724949614908 140724949618672 0 $ more /proc/pid/status Name: bianchengzhuji Umask: 0002 State: S (sleeping) Tgid: 16441 Ngid: 0 Pid: 16441 PPid: 6335是不是发现名字变了呢?虽然进程名还是hello,但是killall已经找不到它了,不过: $ killall bianchengzhuji还是可以的。 为什么会出现这种情况呢? 想象一下,你们公司内部不想重复造轮子,搞了一套开发框架,main函数在框架里写好了,通过库的形式给你们使用,可能名字早就定好了。或者是多线程程序,它的名字是main。 但是,这里需要特别注意的是,如果名字超过了15个字符,在stat和status文件中看到的将会看到被截断的名字。 玩点刺激的既然看到这里了,不如再玩点刺激的。 看看下面的代码: //来源:公众号【编程珠玑】 #include #include #include int main(int argc,char *argv[]) { strncpy(argv[0],"bianchengzhuji",sizeof("bianchengzhuji")); sleep(100); return 0; }是不是发现和前面例子的main函数不一样?参考这里(《C语言的main到底该怎么写》) 这个时候你去编译运行: $ gcc -o hello hello.c $ ./hello然后尝试使用ps去查找进程: $ ps -ef|grep hello root 17831 17818 0 16:09 pts/26 00:00:00 grep --color=auto hello然后你就会惊喜的发现找不到hello进程。 但是使用: $ ps -ef|grep shouwangxiansheng root 17938 6335 0 16:12 pts/4 00:00:00 shouwangxiansheng root 17954 17924 0 16:12 pts/27 00:00:00 grep --color=auto shouwangxiansheng hyb@ub就可以找到。 这种情况下直接改变了程序的命令名,因此ps之类的找不到。 这个时候看命令名是什么呢? $ cat /proc/17938/cmdline shouwangxiansheng不过这个时候killall还是可以找到它!也就是你可以使用killall hello杀死它。 总结如果你发现你的程序无法通过killall 进程名的方式杀死的话,不妨看看proc文件系统中这个进程的stat文件或者status文件中的名。 推荐阅读: 每天都在用printf,你知道变长参数是怎么实现的吗 几个命令了解ELF文件的”秘密“
首发:公众号【编程珠玑】 作者:守望先生 ID:shouwangxiansheng 关注公众号【编程珠玑】,获取更多Linux/C/C++/算法/计算机基础/工具等原创技术文章。后台免费获取经典电子书和视频资源 |
CopyRight 2018-2019 实验室设备网 版权所有 |